package com.zhuoyue.web.controller.system;

import com.alibaba.fastjson.JSONObject;
import com.zhuoyue.common.annotation.Log;
import com.zhuoyue.common.core.controller.BaseController;
import com.zhuoyue.common.core.domain.AjaxResult;
import com.zhuoyue.common.core.domain.entity.SysUser;
import com.zhuoyue.common.core.domain.entity.TblProductBrand;
import com.zhuoyue.common.core.domain.entity.TblProductClassify;
import com.zhuoyue.common.core.domain.entity.TblProductSeries;
import com.zhuoyue.common.core.page.TableDataInfo;
import com.zhuoyue.common.enums.BusinessType;
import com.zhuoyue.common.utils.DealLogUtils;
import com.zhuoyue.common.utils.SecurityUtils;
import com.zhuoyue.common.utils.ServletUtils;
import com.zhuoyue.common.utils.poi.ExcelUtil;
import com.zhuoyue.system.domain.SysReleaseLog;
import com.zhuoyue.system.service.ISysProductManageService;
import com.zhuoyue.system.service.ISysReleaseLogService;
import com.zhuoyue.web.utils.EncryptUtils;
import com.zhuoyue.web.utils.OrgCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.List;
import java.util.UUID;

/**
 * @Author zhanghui
 * @Date: 2021/08/04/9:01
 * @Description: 产品管理
 */
@RestController
@RequestMapping("/system/product")
public class SysProductManage extends BaseController {
    @Autowired
    private ISysProductManageService productManageService;

    @Autowired
    private ISysReleaseLogService releaseLogService;

    @Autowired
    private OrgCodeUtils orgCodeUtils;

    @Autowired
    private DealLogUtils dealLogUtils;

    /**
     * 查询品牌列表
     *
     * @param brand
     * @return
     */
    @GetMapping("/brand/list")
    public TableDataInfo getBrandList(TblProductBrand brand) {
        startPage();
        List<TblProductBrand> tblProductBrands = productManageService.selectBrandList(brand);
        return getDataTable(tblProductBrands);
    }

    @GetMapping("/brand/export")
    public AjaxResult exportBrandList(TblProductBrand brand) {
        List<TblProductBrand> tblProductBrands = productManageService.selectBrandList(brand);
        ExcelUtil<TblProductBrand> util = new ExcelUtil<>(TblProductBrand.class);
        return util.exportExcel(tblProductBrands, "产品品牌");
    }

    @Log(title = "产品品牌添加", businessType = BusinessType.INSERT)
    @PostMapping("/brand/add")
    public AjaxResult brandAdd(@RequestBody TblProductBrand brand) {
//        if (Constants.NOT_UNIQUE.equals(productManageService.checkBrandNameUnique(brand.getBrandName()))) {
//            return AjaxResult.error("新增品牌'" + brand.getBrandName() + "'失败，该品牌已存在");
//        }

        String classAndMethodName = this.getClass().getName() + "." + "brandAdd()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        brand.setCreateBy(SecurityUtils.getUsername());
        productManageService.insertBrand(brand);

        // 添加后的数据
        TblProductBrand targetData = productManageService.selectBrandById(brand.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, null, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品品牌修改", businessType = BusinessType.UPDATE)
    @PutMapping("/brand/update")
    public AjaxResult brandUpdate(@RequestBody TblProductBrand brand) {
//        if (Constants.NOT_UNIQUE.equals(productManageService.checkBrandNameUnique(brand.getBrandName()))) {
//            return AjaxResult.error("修改品牌名称'" + brand.getBrandName() + "'失败，该名称已存在");
//        }

        // 修改前的数据
        TblProductBrand sourceData = productManageService.selectBrandById(brand.getId());
        String classAndMethodName = this.getClass().getName() + "." + "brandUpdate()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        // 修改数据
        brand.setUpdateBy(SecurityUtils.getUsername());
        productManageService.updateBrand(brand);

        // 修改后的数据
        TblProductBrand targetData = productManageService.selectBrandById(brand.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品品牌删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/brand/delete/{brandIds}")
    public AjaxResult brandDelete(@PathVariable Long[] brandIds) {
        // 删除前的数据
        TblProductBrand sourceData = productManageService.selectBrandById(brandIds[0]);
        String classAndMethodName = this.getClass().getName() + "." + "brandDelete()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        productManageService.deleteBrandByIds(brandIds);

        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, null);
        return AjaxResult.success();
    }

    @GetMapping("/classify/list")
    public TableDataInfo getClassifyList(TblProductClassify classify) {
        List<TblProductClassify> classifyList = productManageService.selectClassifyList(classify);
        return getDataTable(classifyList);
    }

    @GetMapping("/classify/export")
    public AjaxResult exportClassifyList(TblProductClassify classify) {
        List<TblProductClassify> classifyList = productManageService.selectClassifyList(classify);
        ExcelUtil<TblProductClassify> util = new ExcelUtil<>(TblProductClassify.class);
        return util.exportExcel(classifyList, "产品分类");
    }

    @Log(title = "产品分类添加", businessType = BusinessType.INSERT)
    @PostMapping("/classify/add")
    public AjaxResult classifyAdd(@RequestBody TblProductClassify classify) {
        String classAndMethodName = this.getClass().getName() + "." + "classifyAdd()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        classify.setCreateBy(SecurityUtils.getUsername());
        productManageService.insertClassify(classify);

        // 添加后的数据
        TblProductClassify targetData = productManageService.selectClassifyById(classify.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, null, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品分类修改", businessType = BusinessType.UPDATE)
    @PutMapping("/classify/update")
    public AjaxResult classifyUpdate(@RequestBody TblProductClassify classify) {
        // 修改前的数据
        TblProductClassify sourceData = productManageService.selectClassifyById(classify.getId());
        String classAndMethodName = this.getClass().getName() + "." + "classifyUpdate()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        // 修改数据
        classify.setUpdateBy(SecurityUtils.getUsername());
        productManageService.updateClassify(classify);

        // 修改后的数据
        TblProductClassify targetData = productManageService.selectClassifyById(classify.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品分类删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/classify/delete/{classifyIds}")
    public AjaxResult classifyDelete(@PathVariable Long[] classifyIds) {
        // 删除前的数据
        TblProductClassify sourceData = productManageService.selectClassifyById(classifyIds[0]);
        String classAndMethodName = this.getClass().getName() + "." + "classifyDelete()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        for (Long classifyId : classifyIds) {
            TblProductClassify classify = productManageService.selectClassifyById(classifyId);

            int childrenCount = productManageService.selectClassifyChildrenCountByParentId(classifyId);
            if (childrenCount > 0) {
                return AjaxResult.error("删除 '" + classify.getClassifyName() + "' 失败，该分类下存在子分类");
            }

            int seriesCount = productManageService.selectSeriesCountByClassifyId(classifyId);
            if (seriesCount > 0) {
                return AjaxResult.error("删除 '" + classify.getClassifyName() + "' 失败，该分类下存在产品系列");
            }
        }

        productManageService.deleteClassifyByIds(classifyIds);

        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, null);
        return AjaxResult.success();
    }

    @GetMapping("/series/list")
    public TableDataInfo getSeriesList(TblProductSeries series) {
        List<TblProductSeries> seriesList = productManageService.selectSeriesList(series);
        return getDataTable(seriesList);
    }

    @GetMapping("/series/export")
    public AjaxResult exportSeriesList(TblProductSeries series) {
        List<TblProductSeries> seriesList = productManageService.selectSeriesList(series);
        ExcelUtil<TblProductSeries> util = new ExcelUtil<>(TblProductSeries.class);
        return util.exportExcel(seriesList, "产品系列");
    }

    @Log(title = "产品系列添加", businessType = BusinessType.INSERT)
    @PostMapping("/series/add")
    public AjaxResult seriesAdd(@RequestBody TblProductSeries series) {
        String classAndMethodName = this.getClass().getName() + "." + "seriesAdd()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        series.setCreateBy(SecurityUtils.getUsername());
        productManageService.insertSeries(series);

        // 添加后的数据
        TblProductSeries targetData = productManageService.selectSeriesById(series.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, null, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品系列修改", businessType = BusinessType.UPDATE)
    @PutMapping("/series/update")
    public AjaxResult seriesUpdate(@RequestBody TblProductSeries series) {
        // 修改前的数据
        TblProductClassify sourceData = productManageService.selectClassifyById(series.getId());
        String classAndMethodName = this.getClass().getName() + "." + "seriesUpdate()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        series.setUpdateBy(SecurityUtils.getUsername());
        productManageService.updateSeries(series);

        // 修改后的数据
        TblProductClassify targetData = productManageService.selectClassifyById(series.getId());
        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, targetData);
        return AjaxResult.success();
    }

    @Log(title = "产品系列删除", businessType = BusinessType.DELETE)
    @DeleteMapping("/series/delete/{seriesIds}")
    public AjaxResult seriesDelete(@PathVariable Long[] seriesIds) {
        // 删除前的数据
        TblProductSeries sourceData = productManageService.selectSeriesById(seriesIds[0]);
        String classAndMethodName = this.getClass().getName() + "." + "seriesDelete()";
        SysUser user = orgCodeUtils.getLoginUser(ServletUtils.getRequest()).getUser();

        productManageService.deleteSeriesByIds(seriesIds);

        dealLogUtils.setRedisSourceAndTargetData(classAndMethodName, user, sourceData, null);
        return AjaxResult.success();
    }

    @GetMapping("/series/listByClassifyId/{classifyId}")
    public TableDataInfo getSeriesByClassifyId(@PathVariable Long classifyId) {
        List<TblProductSeries> seriesList = productManageService.selectSeriesByClassifyId(classifyId);
        return getDataTable(seriesList);
    }


    @Value("${release-dispatch.url}")
    private String dispatchUrl;

    /**
     * 产品发布
     *
     * @return
     */
    @Log(title = "产品发布", businessType = BusinessType.UPDATE)
    @PostMapping("/productRelease")
    public AjaxResult productRelease() {
        try {
            productManageService.releaseData();
        } catch (RuntimeException e) {
            e.printStackTrace();
            return AjaxResult.error("发布失败");
        }

        // 转发发布通知请求
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> result = restTemplate.getForEntity(dispatchUrl, String.class);
        if (result.getStatusCode() != HttpStatus.OK) {
            AjaxResult.error("发布失败");
        }


        // 添加产品发布日志
        SysReleaseLog sysReleaseLog = new SysReleaseLog();
        sysReleaseLog.setId(UUID.randomUUID().toString().replace("-", "").toLowerCase());
        sysReleaseLog.setCreateBy(SecurityUtils.getUsername());
        releaseLogService.insertReleaseLog(sysReleaseLog);
        return AjaxResult.success();
    }

    @Autowired
    private EncryptUtils encryptUtils;

    @GetMapping("test1")
    public AjaxResult test1(HttpServletRequest request) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IOException, InvalidKeyException {
        String params = request.getParameter("params");
        String decrypt = encryptUtils.rasDecrypt(encryptUtils.base64Decode(params));
        JSONObject jsonObject = JSONObject.parseObject(decrypt);
        String userId = jsonObject.get("userId").toString();
        String deptId = jsonObject.get("deptId").toString();
        return AjaxResult.success();
    }

    /**
     * @param request
     * @return
     * @RequestBody SysUser user
     */
    @PostMapping("test2")
    public AjaxResult test2(HttpServletRequest request) throws NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidKeySpecException, BadPaddingException, IOException, InvalidKeyException {
        String params = request.getParameter("params");
        String decrypt = encryptUtils.rasDecrypt(encryptUtils.base64Decode(params));
        SysUser sysUser = JSONObject.parseObject(decrypt, SysUser.class);
        return AjaxResult.success();
    }

    @PostMapping("test3")
    public AjaxResult test3(@RequestBody SysUser user) {
        return AjaxResult.success();
    }
}
